/*
 * Copyright 2010,2011 Michael Nitsche
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.mnit.basis.daten.typ.zeit;

import java.util.Calendar;
import java.util.GregorianCalendar;

import de.mnit.basis.daten.FilterText;
import de.mnit.basis.daten.typ.A_Datentyp;
import de.mnit.basis.daten.typ.zeit.format.FormatZeit;
import de.mnit.basis.fehler.Fehler;
import de.mnit.basis.fehler.system.F_Programm;

/**
 * @author Michael Nitsche
 */
public class Zeitpunkt extends A_Datentyp<S_Zeitpunkt> implements S_Zeitpunkt {

	private final S_Datum   datum;
	private final S_Uhrzeit uhrzeit;


	public Zeitpunkt() {
		this.datum	=new Datum();
		this.uhrzeit=new Uhrzeit();
	}

	public Zeitpunkt(S_Datum datum, S_Uhrzeit uhrzeit) {
		Fehler.objekt.wenn_Null(datum, uhrzeit);
		this.datum	=datum;
		this.uhrzeit=uhrzeit;
	}

	public Zeitpunkt(Calendar c) {
		Fehler.objekt.wenn_Null(c);
		this.datum  = new Datum(c);
		this.uhrzeit= new Uhrzeit(c);
	}

	public Zeitpunkt(long ms) {
		GregorianCalendar c=new GregorianCalendar();
		c.setTimeInMillis(ms);
		this.datum  = new Datum(c);
		this.uhrzeit= new Uhrzeit(c);
	}

	public Zeitpunkt(String zeitpunkt) {
		Fehler.text.wenn_Null_o_Leer(zeitpunkt);
		try {
			//TODO 2003-02-01 12:34

			// 01.02.2003 12:34
			if(zeitpunkt.matches("[0-3][0-9].[0-1][0-9].[1-2][0-9][0-9][0-9] [0-2][0-9]:[0-5][0-9]")) {
				this.datum  = new Datum(FilterText.teil( 1,10,zeitpunkt));
				this.uhrzeit= new Uhrzeit(FilterText.teil(12, 5,zeitpunkt));
			}
			// 01.02.2003 12:34:56
			else if(zeitpunkt.matches("[0-3][0-9].[0-1][0-9].[1-2][0-9][0-9][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]")) {
				this.datum  = new Datum(FilterText.teil( 1,10,zeitpunkt));
				this.uhrzeit= new Uhrzeit(FilterText.teil(12, 8,zeitpunkt));
			}
			// 2003-02-01 12:34:56
			else if(zeitpunkt.matches("[1-2][0-9][0-9][0-9].[0-1][0-9].[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]")) {
				this.datum  = new Datum(FilterText.teil( 1,10,zeitpunkt));
				this.uhrzeit= new Uhrzeit(FilterText.teil(12, 8,zeitpunkt));
			}
			// 20030201123456
			else if(zeitpunkt.matches("[1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9][0-2][0-9][0-5][0-9][0-5][0-9]")) {
				this.datum	= new Datum(FilterText.teil(1,4,zeitpunkt)+"-"+FilterText.teil(5,2,zeitpunkt)+"-"+FilterText.teil(7,2,zeitpunkt));
				this.uhrzeit= new Uhrzeit(FilterText.teil(9,2,zeitpunkt)+":"+FilterText.teil(11,2,zeitpunkt)+":"+FilterText.teil(13,2,zeitpunkt));
			}
			else throw Fehler.text.da_Ungueltig("Unbekanntes Zeitformat!");
		}
		catch(F_Programm f) {
			throw f;
		}
		catch(Exception  e) {
			throw Fehler.text.da_Ungueltig("Zeitpunkt fehlerhaft!");
		}
	}


	public static Zeitpunkt neu() {
		return new Zeitpunkt();
	}

	public static Zeitpunkt neu(long msek) {
		return new Zeitpunkt(msek);
	}

	public static Zeitpunkt neu(String string) {
		return new Zeitpunkt(string);
	}

	public static Zeitpunkt neu(S_Datum datum, S_Uhrzeit uhrzeit) {
		return new Zeitpunkt(datum,uhrzeit);
	}


	public S_Uhrzeit	gUhrzeit() 		{ return this.uhrzeit; }
	public int 			gStunden()		{ return this.uhrzeit.gStunden(); }
	public int 			gMinuten()		{ return this.uhrzeit.gMinuten(); }
	public int 			gSekunden()		{ return this.uhrzeit.gSekunden(); }
	public S_Datum 		gDatum()		{ return this.datum; }
	public int 			gJahr()			{ return this.datum.gJahr(); }
	public int 			gMonat()		{ return this.datum.gMonat(); }
	public int 			gTag()			{ return this.datum.gTag(); }

	public int diffStd(S_Zeitpunkt z) { //TODO Prüfen!
		long aktuell=Zeit.zuMilliSek(this.gJahr(), this.gMonat(), this.gTag(), this.gStunden(), this.gMinuten(), this.gSekunden(), 0);
		long ziel   =Zeit.zuMilliSek(z.gJahr(), z.gMonat(), z.gTag(), z.gStunden(), z.gMinuten(), z.gSekunden(), 0);
		long diff_ms=ziel-aktuell;
		return (int)(diff_ms/1000/3600);
	}

//	public int diffTage(S_Zeitpunkt d) { //TODO Prüfen!
//		int tage=this.gDatum().diffTage(d.gDatum());
//		if(!this.gUhrzeit().istGroesser(d.gUhrzeit()))
//			tage--;
//		return tage;
//	}

	public boolean istGroesser(S_Zeitpunkt z) {
		long aktuell=Zeit.zuMilliSek(this.gJahr(), this.gMonat(), this.gTag(), this.gStunden(), this.gMinuten(), this.gSekunden(), 0);
		long ziel   =Zeit.zuMilliSek(z.gJahr(), z.gMonat(), z.gTag(), z.gStunden(), z.gMinuten(), z.gSekunden(), 0);
		long diff_ms=aktuell-ziel;
		return diff_ms>0;
	}

	public String toString()				{ return FormatZeit.zuText(this); }
	public String zuTextEDV() 				{ return FormatZeit.zuTextEDV(this); }
	public String zuTextDS() 				{ return FormatZeit.zuTextDS(this); }
	public String zuText(Object... format)	{ return FormatZeit.zuText(this, format); }

	public boolean istGleich(S_Zeitpunkt zeit) {
		return this.datum.istGleich(zeit.gDatum()) && this.uhrzeit.istGleich(zeit.gUhrzeit());
	}

	public S_Zeitpunkt gPlusTag(int anzahl) {
		long aktuell=Zeit.zuMilliSek(this.gJahr(), this.gMonat(), this.gTag(), this.gStunden(), this.gMinuten(), this.gSekunden(), 0);
		aktuell+=((long)anzahl)*24*60*60*1000;
		return Zeitpunkt.neu(aktuell);
	}

	public S_Zeitpunkt gPlusStd(int anzahl) {
		long aktuell=Zeit.zuMilliSek(this.gJahr(), this.gMonat(), this.gTag(), this.gStunden(), this.gMinuten(), this.gSekunden(), 0);
		aktuell+=((long)anzahl)*60*60*1000;
		return Zeitpunkt.neu(aktuell);
	}

}
